#include "USB_monitor.h"
#ifdef LINUX_USB_MONITOR_MOD
#include <QDebug>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <errno.h>
#include <unistd.h>
#include <QMutex>

#define UEVENT_BUFFER_SIZE      2048
static int init_hotplug_sock(void);

USBMonitor::USBMonitor(QObject *parent)
{
    (void *)parent;
}

USBMonitor::~USBMonitor()
{
    qDebug() << __FUNCTION__ << " called";
}

void USBMonitor::slotUSBMonitorExec()
{
    if (running) return ;
    setRunning(true);
    hotplug_sock       = init_hotplug_sock();
    while (running)
    {
        char buf[UEVENT_BUFFER_SIZE*2] = {0};
        QThread::msleep(100);
        if (recv(hotplug_sock, &buf, sizeof(buf), MSG_DONTWAIT) <= 0) {
            continue;
        }
        QString data(buf);
        emit sigUSBDetected(data);
    }
    qDebug() << "Exit USB Monitor";
}

void USBMonitor::setRunning(bool run)
{
    static QMutex mtx;
    mtx.lock();
    running = run;
    mtx.unlock();
}

void USBMonitor::stop()
{
    shutdown(hotplug_sock,SHUT_RDWR);
    close(hotplug_sock);
    qDebug() << "stop USB Monitor";
    setRunning(false);
}

static int init_hotplug_sock(void)
{
    struct sockaddr_nl snl;
    const int buffersize = 16 * 1024 * 1024;
    int retval;

    memset(&snl, 0x00, sizeof(struct sockaddr_nl));
    snl.nl_family = AF_NETLINK;
    snl.nl_pid = getpid();
    snl.nl_groups = 1;

    int hotplug_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
    if (hotplug_sock == -1)
    {
        qDebug("error getting socket: %s", strerror(errno));
        return -1;
    }

    /* set receive buffersize */
    setsockopt(hotplug_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));
    retval = bind(hotplug_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl));
    if (retval < 0) {
        qDebug("bind failed: %s", strerror(errno));
        close(hotplug_sock);
        hotplug_sock = -1;
    }
    return hotplug_sock;
}


#endif
